package cc.rengu.igas.share.core.service.channel.upac;

import cc.rengu.igas.channel.upac.facade.base.Header;
import cc.rengu.igas.channel.upac.facade.request.B2cTransStateQueryRequest;
import cc.rengu.igas.channel.upac.facade.response.B2cTransStateQueryResponse;
import cc.rengu.igas.channel.upac.facade.response.TokenTransStateQueryRespone;
import cc.rengu.igas.channel.upac.facade.result.Result;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.constant.ShareServiceConstant;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.common.enums.FeeTypeEnum;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * UPAC-网关交易状态查询
 * Created by lzl on 2021/4/23 11:08
 */
public class B2cTransStateQueryService extends ChannelBaseService {
    @Override
    public Object callPreProc(TxnInfo txnInfo, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        Header upacHeader = new Header();
        upacHeader.setInstId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.INST_ID));
        upacHeader.setChanlId(channelCallCfg.getMsgSrcId());
        upacHeader.setSrcSysId(AppParamConstant.SYS_ID);
        upacHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        upacHeader.setVersion(ShareParamConstant.DUBBO_VSERSION);
        upacHeader.setTxnNum(channelCallCfg.getCallChannelTxn());
        upacHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + channelCallCfg.getCallIndex());
        upacHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        upacHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        B2cTransStateQueryRequest b2cTransStateQueryRequest = new B2cTransStateQueryRequest();
        ConvertUtil.convertOutput(b2cTransStateQueryRequest);
        b2cTransStateQueryRequest.setHeader(upacHeader);

        String prodType = "";
        String upacMchntNo = "";
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = mchntService.getMchntInfo(upacHeader.getInstId(), orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
        if (null == mchntInfo) {
            rglog.error("获取商户信息失败,mchntNo:<{}>", orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
            return null;
        }
        Map<String, Object> mchntMap = JSONObject.parseObject(mchntInfo.getCupsChannelMchntNo());
        for (Map.Entry entry : mchntMap.entrySet()) {
            if (((String) entry.getKey()).startsWith("GW")) {
                prodType = (String) entry.getKey();
                upacMchntNo = (String) entry.getValue();
                break;
            }
        }
        if (upacMchntNo == null) {
            rglog.error("商户<{}>未开通银联业务，不支持银联token支付！", orderInfo.getMchntOrderInfoList().get(0).getMchntNo());
            return null;
        }
        b2cTransStateQueryRequest.setAccessType("0");
        b2cTransStateQueryRequest.setProdType(prodType);
        b2cTransStateQueryRequest.setUpacMchntNo(upacMchntNo);
        b2cTransStateQueryRequest.setChannelType("07");
        Predicate<PayOrderInfo> channelFilter = p -> channelCallCfg.getCallChannelId().equals(p.getMsgDstId());
        List<PayOrderInfo> payOrderInfoList = orderInfo.getPayOrderInfoList().stream().filter(channelFilter).collect(Collectors.toList());
        b2cTransStateQueryRequest.setOrderId(payOrderInfoList.get(0).getSysSeqNum());
        b2cTransStateQueryRequest.setOrderTime(payOrderInfoList.get(0).getTxnDate() + payOrderInfoList.get(0).getTxnTime());
        rglog.debug("UPAC 网关交易状态查询请求:<{}>", JSON.toJSONString(b2cTransStateQueryRequest));
        return b2cTransStateQueryRequest;
    }

    @Override
    public PayOrderInfo generatePayOrderInfo(ChannelCallCfg channelCallCfg, OrderInfo orderInfo, Object request) throws Exception {
        //此交易不登记支付订单
        return null;
    }

    @Override
    public Object callProc(ChannelCallCfg channelCallCfg, Object request) throws Exception {
        B2cTransStateQueryRequest b2cTransStateQueryRequest = (B2cTransStateQueryRequest) request;
        /* Step1：调用接口，获取结果 */
        Result<B2cTransStateQueryResponse> callResult;
        DubboService dubboService = new DubboServiceImpl();
        if (AppParamConstant.YES.equals(channelCallCfg.getSyncCallFlag())) {
            /* Step1.1：异步调用 */
            int iReturnCode;
            int callTimes = 0 == channelCallCfg.getSyncQueryRepeatNum() ? 1 : channelCallCfg.getSyncQueryRepeatNum();
            int gatTime = channelCallCfg.getSyncQueryRepeatTime();
            int gatType = StringUtil.isEmptyOrNull(channelCallCfg.getSyncQueryGapType()) ? 0 : Integer.parseInt(channelCallCfg.getSyncQueryGapType());
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.1：异步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPAC_GATEWAY_SERVICE_INNER_PATH);
                iReturnCode = dubboService.asynCallDubboInnerMethod(clasz, ShareServiceConstant.UPAC_B2C_TRANS_STATE_QUERY_METHOD, b2cTransStateQueryRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.1.2：异步远程调用 */
                iReturnCode = dubboService.asynCallDubboService(ShareServiceConstant.UPAC_GATEWAY_SERVICE, ShareServiceConstant.UPAC_B2C_TRANS_STATE_QUERY_METHOD, b2cTransStateQueryRequest, channelCallCfg.getSyncResultServiceName(), callTimes, gatType, gatTime);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
            if (0 == iReturnCode) {
                return new BizResponse<>(OltpRpcdEnum.TRANS_SUCCESS.getRespCode(), OltpRpcdEnum.TRANS_SUCCESS.getRespDesc());
            } else {
                return new BizResponse<>(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            }
        } else {
            /* Step1.2：同步调用 */
            if (ChannelCallModeEnum.LOCAL.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.1：同步应用内调用 */
                Class clasz = Class.forName(ShareServiceConstant.UPAC_GATEWAY_SERVICE_INNER_PATH);
                callResult = (Result<B2cTransStateQueryResponse>) dubboService.callDubboInnerMethod(clasz, ShareServiceConstant.UPAC_B2C_TRANS_STATE_QUERY_METHOD, b2cTransStateQueryRequest);
            } else if (ChannelCallModeEnum.REMOTE.getMode().equals(channelCallCfg.getChannelCallMode())) {
                /* Step1.2.2：同步远程调用 */
                callResult = (Result<B2cTransStateQueryResponse>) dubboService.callDubboService(ShareServiceConstant.UPAC_GATEWAY_SERVICE, ShareServiceConstant.UPAC_B2C_TRANS_STATE_QUERY_METHOD, b2cTransStateQueryRequest);
            } else {
                rglog.error("不支持的通道服务调用方式:{}，交易拒绝!", channelCallCfg.getChannelCallMode());
                throw new BizException(OltpRpcdEnum.CALL_BIZ_SERVICE_ERROR);
            }
        }
        return callResult;
    }

    @Override
    public Object querySyncCallResult(PayOrderInfo payOrderInfo, Object request) {
        return null;
    }

    @Override
    public OrderInfo callResultOrderProc(OrderInfo orderInfo, String payOrderIndex, TransStatusEnum transStatusEnum, Object response) throws Exception {
        OrderInfo updateOrderInfo = new OrderInfo();
        Result<B2cTransStateQueryResponse> callResult = (Result<B2cTransStateQueryResponse>) response;
        Optional<PayOrderInfo> payOrderInfoOpt = orderInfo.getPayOrderInfoList().stream().filter(item -> item.getDstCallIndex().equals(payOrderIndex)).findFirst();
        if (payOrderInfoOpt.isPresent() && null != callResult && null != callResult.getResult()) {
            UserOrderInfo userOrderInfo = orderInfo.getUserOrderInfo();
            List<MchntOrderInfo> mchntOrderInfoList = orderInfo.getMchntOrderInfoList();
            PayOrderInfo payOrderInfo = payOrderInfoOpt.get();
            B2cTransStateQueryResponse b2cTransStateQueryResponse = callResult.getResult();
            switch (transStatusEnum) {
                case TRANS_SUCC:
                    if (OltpRpcdEnum.TRANS_SUCCESS.getRespCode().equals(b2cTransStateQueryResponse.getOrigRespCode())) {
                        /* 更新当前用户订单信息 */
                        userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                        userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                        userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        /* 更新当前商户订单信息*/
                        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                            mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                            mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        }
                        /*计算商户手续费及优惠 */
                        if (!"00".equals(mchntOrderInfoList.get(0).getBizSceneType()) && !"02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
                            String feeType = FeeTypeEnum.OTHER_BANK_CR_CARD.getFeeType();
                            if ("01".equals(b2cTransStateQueryResponse.getPayCardType())) {
                                feeType = FeeTypeEnum.OTHER_BANK_DR_CARD.getFeeType();
                            }
                            MchntService mchntService = new MchntServiceImpl();
                            mchntService.calcMchntFee(mchntOrderInfoList, feeType);
                        }
                        /* 更新支付订单信息 */
                        if ("01".equals(b2cTransStateQueryResponse.getPayCardType())) {
                            payOrderInfo.setPayerAcctType(AcctTypeEnum.OTHER_DEBIT.getAcctType());
                        } else if ("02".equals(b2cTransStateQueryResponse.getPayCardType()) ||
                                "03".equals(b2cTransStateQueryResponse.getPayCardType()) ||
                                "04".equals(b2cTransStateQueryResponse.getPayCardType())) {
                            payOrderInfo.setPayerAcctType(AcctTypeEnum.OTHER_CREDIT.getAcctType());
                        } else {
                            payOrderInfo.setPayerAcctType(AcctTypeEnum.ALL.getAcctType());
                        }
                        payOrderInfo.setChannelSeqNum(b2cTransStateQueryResponse.getChannelSeqNum());
                        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                        payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                        payOrderInfo.setSettleDate(b2cTransStateQueryResponse.getSettleDate());
                        payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        updateOrderInfo.setUserOrderInfo(userOrderInfo);
                        updateOrderInfo.setMchntOrderInfoList(mchntOrderInfoList);
                    } else {
                        /* 更新当前用户订单信息 */
                        userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                        userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                        userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                        userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        /* 更新当前商户订单信息 */
                        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                            mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                            mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                            mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        }
                        /* 更新当前支付订单信息 */
                        payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                        payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                        payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                        updateOrderInfo.setUserOrderInfo(userOrderInfo);
                        updateOrderInfo.setMchntOrderInfoList(mchntOrderInfoList);
                    }
                    break;
                case TRANS_TIMEOUT:
                    payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                    break;
                case SYSTEM_REJECT:
                    /* 更新当前用户订单信息 */
                    userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
                    userOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    userOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    /* 更新当前商户订单信息 */
                    for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                        mchntOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                        mchntOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                        mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    }
                    /* 更新当前支付订单信息 */
                    payOrderInfo.setTransStatus(TransStatusEnum.SYSTEM_REJECT.getStatus());
                    payOrderInfo.setBizStatus(BizStatusEnum.FAILED.getStatus());
                    payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
                    updateOrderInfo.setUserOrderInfo(userOrderInfo);
                    updateOrderInfo.setMchntOrderInfoList(mchntOrderInfoList);
                    break;
                default:
                    break;
            }
            List<PayOrderInfo> payOrderInfoList = new ArrayList<>();
            payOrderInfoList.add(payOrderInfo);
            updateOrderInfo.setPayOrderInfoList(payOrderInfoList);
        }
        return updateOrderInfo;
    }
}
